package cn.blossoming.service.tips.impl;

import cn.blossoming.dao.domain.*;
import cn.blossoming.service.base.SessionService;
import cn.blossoming.service.base.exception.ServiceException;
import cn.blossoming.service.base.impl.BaseServiceImpl;
import cn.blossoming.service.dto.Tips;
import cn.blossoming.service.dto.TipsComment;
import cn.blossoming.service.dto.TipsPicture;
import cn.blossoming.service.dto.User;
import cn.blossoming.service.tips.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Example;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Sort;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.List;
import java.util.stream.Collectors;

@Service
public class TipsServiceImpl extends BaseServiceImpl<TipsEntity, Integer> implements TipsService, SessionService {

    @Autowired
    private TipsPraiseService tipsPraiseService;
    @Autowired
    private TipsCommentService tipsCommentService;
    @Autowired
    private TipsReadService tipsReadService;
    @Autowired
    private TipsCommentPraiseService tipsCommentPraiseService;


    @Override
    public List<Tips> findPage(PageRequest pageRequest) {
        UserEntity currentUserEntity = UserEntity.builder().id(getCurrentUserId()).build();
        Page<TipsEntity> page = this.findAll(pageRequest);
        return page.getContent().stream().map(entity -> {
            Tips tips = new Tips(entity);
            UserEntity userEntity = entity.getUser();
            tips.setUser(User.builder().name(userEntity.getName()).avatar(userEntity.getAvatar()).build());
            tips.setPraise(tipsPraiseService.exists(Example.of(TipsPraiseEntity.builder().tips(entity).user(currentUserEntity).build())));
            return tips;
        }).collect(Collectors.toList());
    }

    @Override
    public Tips getTipsById(int id) {
        TipsEntity tipsEntity = this.findOne(id);
        TipsReadEntity readEntity = TipsReadEntity.builder().user(UserEntity.builder().id(getCurrentUserId()).build()).build();
        if (!tipsReadService.exists(Example.of(readEntity))) {//是否已读
            readEntity.setTips(tipsEntity);
            tipsReadService.save(readEntity);
            tipsEntity.setReadNum(tipsEntity.getReadNum() + 1);
            this.save(tipsEntity);
        }

        Tips tips = new Tips(tipsEntity);
        tips.setTipsPictures(tipsEntity.getTipsPictures().stream().map(TipsPicture::new).collect(Collectors.toList()));
        tips.setUser(new User(tipsEntity.getUser()));
        tips.setPraise(tipsPraiseService.exists(Example.of(TipsPraiseEntity.builder().tips(tipsEntity).user(UserEntity.builder().id(getCurrentUserId()).build()).build())));
        tips.setMyself(getCurrentUserId().equals(tips.getUser().getId()));
        List<TipsComment> comments = getCommentsByTipsId(tips.getId(), new PageRequest(1, 10, Sort.Direction.DESC, "id"));
        tips.setTipsComments(comments);
        tips.setTipsTags(tipsEntity.getTipsTags());
        return tips;
    }

    @Override
    @Transactional
    public Tips praiseTips(int id) {
        TipsPraiseEntity praise = new TipsPraiseEntity();
        praise.setUser(UserEntity.builder().id(getCurrentUserId()).build());
        praise.setTips(TipsEntity.builder().id(id).build());
        if (tipsPraiseService.exists(Example.of(praise)))
            throw new ServiceException(420, "你已经赞过了");
        tipsPraiseService.save(praise);
        TipsEntity tipsEntity = this.findOne(id);
        tipsEntity.setPraiseNum(tipsEntity.getPraiseNum() + 1);
        this.save(tipsEntity);
        Tips Tips = new Tips(tipsEntity);
        Tips.setUser(new User(tipsEntity.getUser()));
        Tips.setMyself(getCurrentUserId().equals(Tips.getUser().getId()));
        return Tips;
    }

    @Override
    public List<TipsComment> getCommentsByTipsId(int id, PageRequest pageRequest) {
        Page<TipsCommentEntity> page = tipsCommentService.findAll(Example.of(TipsCommentEntity.builder().tips(TipsEntity.builder().id(id).build()).build()), pageRequest);
        List<TipsComment> tipsComments = Tips.TipsEntityComments2TipsComments(page.getContent());
        UserEntity currentUserEntity = UserEntity.builder().id(getCurrentUserId()).build();
        tipsComments.forEach(tipsComment -> {
            tipsComment.setPraise(tipsCommentPraiseService.exists(Example.of(TipsCommentPraiseEntity.builder().tipsComment(TipsCommentEntity.builder().id(tipsComment.getId()).build()).user(currentUserEntity).build())));
        });
        return tipsComments;
    }

    @Override
    @Transactional
    public void tipsCommentPraise(int id) {
        TipsCommentEntity entity = tipsCommentService.findOne(id);
        TipsCommentPraiseEntity commentPraiseEntity = new TipsCommentPraiseEntity();
        commentPraiseEntity.setUser(UserEntity.builder().id(getCurrentUserId()).build());
        commentPraiseEntity.setTipsComment(entity);
        if (tipsCommentPraiseService.exists(Example.of(commentPraiseEntity)))//已经赞过了
            throw new ServiceException(420, "你已经赞过了");
        entity.setCommentNum(entity.getCommentNum() + 1);
        tipsCommentPraiseService.save(commentPraiseEntity);
        tipsCommentService.save(entity);
    }

    @Override
    @Transactional
    public void addTipsComment(int id, String content) {
        TipsEntity entity = this.findOne(id);
        entity.setCommentNum(entity.getCommentNum() + 1);
        this.save(entity);
        TipsCommentEntity tipsCommentEntity = new TipsCommentEntity();
        tipsCommentEntity.setTips(entity);
        tipsCommentEntity.setUser(UserEntity.builder().id(getCurrentUserId()).build());
        tipsCommentEntity.setContent(content);
        tipsCommentService.save(tipsCommentEntity);
    }

    @Override
    @Transactional
    public void addTipsCommentComment(int commentId, String content, int TipsId) {
        TipsEntity entity = this.findOne(TipsId);
        entity.setCommentNum(entity.getCommentNum() + 1);
        this.save(entity);
        TipsCommentEntity one = tipsCommentService.findOne(commentId);
        one.setCommentNum(one.getCommentNum() + 1);

        TipsCommentEntity tipsCommentEntity = new TipsCommentEntity();
        tipsCommentEntity.setTipsComment(one);
        tipsCommentEntity.setTips(TipsEntity.builder().id(0).build());
        tipsCommentEntity.setUser(UserEntity.builder().id(getCurrentUserId()).build());
        tipsCommentEntity.setContent(content);
        tipsCommentService.save(one);
        tipsCommentService.save(tipsCommentEntity);
    }

    @Override
    public List<TipsComment> getTipsCommentCommentByCommentId(int commentId, PageRequest pageRequest) {
        TipsCommentEntity parent = TipsCommentEntity.builder().id(commentId).build();
        Page<TipsCommentEntity> page = tipsCommentService.findAll(Example.of(TipsCommentEntity.builder().tipsComment(parent).build()), pageRequest);
        List<TipsComment> tipsComments = Tips.TipsEntityComments2TipsComments(page.getContent());
        UserEntity currentUserEntity = UserEntity.builder().id(getCurrentUserId()).build();
        tipsComments.forEach(t -> t.setPraise(tipsCommentPraiseService.exists(Example.of(TipsCommentPraiseEntity.builder().user(currentUserEntity).tipsComment(TipsCommentEntity.builder().id(t.getId()).build()).build()))));
        return tipsComments;
    }

    @Override
    public List<Tips> findPageByUser(int userId, PageRequest pageRequest) {
        Integer currentUserId = getCurrentUserId();
        UserEntity currentUserEntity = UserEntity.builder().id(currentUserId).build();
        Page<TipsEntity> page = this.findAll(Example.of(TipsEntity.builder().user(UserEntity.builder().id(userId).build()).build()), pageRequest);
        return page.getContent().stream().map(Tips::new).peek(tips -> {
            if (currentUserId.equals(userId))
                tips.setMyself(true);
            tips.setPraise(tipsPraiseService.exists(Example.of(TipsPraiseEntity.builder().user(currentUserEntity).tips(TipsEntity.builder().id(tips.getId()).build()).build())));

        }).collect(Collectors.toList());
    }

}
